/*
 * COMP6471 Project2
 * 
 * Assignment 2: Due 10:00 Thursday 13 October 2011. 
 * Submit a .tar.gz file with your Java program, test input files, and test outputs to 
 * Project 2 of electronic submission system. 
 * A batch Java program to generate game layouts (ie no arithmetic formulas) from a list 
 * of possible cage shapes. 
 * The input is a file with a list of cages. You need to have a text format to describe a 
 * cage. Remember to allow for rotations of cages in your list of input cages. 
 * The output is a file of all layouts that can be constructed from the cages in the input 
 * file in a 4x4 (or 6x6 grid). 
 * Initially restrict the cage shapes to be of size 1, 2, or 3. Allow for L-shaped cage. 
 * So your input file does not have to list all possible cages: start simple and work up. 
 * Initially solve for 4-by-4 case and then the 6-by-6 case.
 * 
 * This file is created by Yuan Tao (ewan.msn@gmail.com)
 * Licensed under GNU GPL v3
 * 
 * $Author: ewan.msn@gmail.com $
 * $Date: 2011-10-12 04:12:44 +0000 (Wed, 12 Oct 2011) $
 * $Rev: 33 $
 * $HeadURL: http://comp6471.googlecode.com/svn/Project2/src/Project2Main.java $
 * 
 */

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import kklib.*;
import util.*;

public class Project2Main {
	
	public static ArrayList<Layout> layouts = new ArrayList<Layout>();

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("Hi, wellcome to COMP6471 Project2. v0.1");
		System.out.println("Developed by Yuan Tao (ewan.msn@gmail.com)\n");
		System.out.println("Please put all the input files under the root directoy of $ThisProgram\\input\\");
		System.out.println("There are already some sample txt files under $input directory.");
		System.out.println("The result of the progrom will store in the file: $ThisProgram\\output\\result.txt \n");
		System.out.println("Then press any key to begin...");
		
		try {
			System.in.read();
		} catch (IOException e) {
			
		}

		// create and initialize the logger
		logger.init();

		// format the result.txt file.
		SimpleDateFormat tmpDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String datetimeNow = tmpDate.format(new java.util.Date());
		logger.output(datetimeNow + "\n");
		
		// load all txt files
		InputLoader txtLoader = new InputLoader();
		String path = System.getProperty("user.dir") + "\\input";
		if (txtLoader.loadTextFiles(path, layouts) != 0) {
			return;
		}

		// checking
		Layout layout = null;
		for (int i = 0; i < layouts.size(); i++) {
			layout = layouts.get(i);

			// logging
			logger.info(layout.fileFullname);
			//logger.info(layout.txtFileData.toString());

			// parse one file
			if (txtLoader.fileDataParserForCages(layout) != 0) {
				continue;
			}
			
			for (int j = 0; j < layout.availableCages.size(); j++) {
				logger.info(layout.availableCages.get(j).cageType + ":" +
						layout.availableCages.get(j).cageNum + " ");
			}
			
			// Generate the possible layouts
			int ret = layout.generatePossibleLayoutFromCages();
			
			logger.output("Input filename: " + layout.fileFullname);
			if (ret == -3) {
				logger.output("Number of possible layouts: > " + Layout.MAX_POSSIBLE_LAYOUTS);
			} else {
				logger.output("Number of possible layouts: " + layout.getNumOfSolutions());
			}
			
			if (ret == -1) {
				logger.output("Error: Too many cages.\n");
			} else if (ret == -2) {
				logger.output("Error: Too few cages.\n");
			} else {
				// print out the result
				//printResult(layout);
				printResultEx(layout);
			}
		}
		
		logger.info("The program ends successfully!");
	}

	// number version
//	private static void printResult(Layout layout) {
//		if (layout == null) {
//			return;
//		}
//		
//		for (int i = 0; i < layout.possibleLayouts.size(); i++) {
//			ArrayList<Integer> lo = layout.possibleLayouts.get(i);
//			for (int j = 0; j < layout.gameSize * layout.gameSize; j++) {
//				System.out.print(lo.get(j).toString() + " ");
//				if ((j + 1) % layout.gameSize == 0) {
//					System.out.println("");
//				}
//			}
//			System.out.println("");
//		}		
//	}
	
	private static void printFirstLine(int gameSize, ArrayList<Integer> lo, StringBuffer buf) {
		if (lo == null) {
			return;
		}
		for (int i = 0; i < gameSize; i++) {
			buf.append(" _");
		}
		buf.append("\t");
	}
	private static void printMidLines(int gameSize, ArrayList<Integer> lo, StringBuffer buf, int j) {
		if (lo == null) {
			return;
		}
		buf.append("|");
		for (int j2 = 0; j2 < gameSize - 1; j2++) {
			if (lo.get(j2 + j * gameSize) != lo.get(j2 + (j + 1) * gameSize)) {
				buf.append("_");
			} else {
				buf.append(" ");
			}
			if (lo.get(j2 + j * gameSize) != lo.get(j2 + 1 + j * gameSize)) {
				buf.append("|");
			} else {
				buf.append(" ");
			}
		}
		int j2 = gameSize - 1;
		if (lo.get(j2 + j * gameSize) != lo.get(j2 + (j + 1) * gameSize)) {
			buf.append("_");
		} else {
			buf.append(" ");
		}
		buf.append("|");
		buf.append("\t");
	}
	private static void printLastLine(int gameSize, ArrayList<Integer> lo, StringBuffer buf) {
		if (lo == null) {
			return;
		}
		buf.append("|");
		for (int j2 = 0; j2 < gameSize - 1; j2++) {
			buf.append("_"); 

			int j = gameSize - 1;
			if (lo.get(j2 + j * gameSize) != lo.get(j2 + 1 + j * gameSize)) {
				buf.append("|");
			} else {
				buf.append(" ");
			}
		}
		buf.append("_|");
		buf.append("\t");
	}

	// more friendly
	private static void printResultEx(Layout layout) {
		if (layout == null) {
			return;
		}
		
		if (layout.getNumOfSolutions() > Layout.MAX_SOLUTIONS) {
			logger.output("Too many layouts. Only the first " + Layout.MAX_SOLUTIONS + " will be printed out:");
		}
		 
		for (int i = 0; i < layout.possibleLayouts.size(); i++) {
			ArrayList<Integer> lo1 = layout.possibleLayouts.get(i++);
			ArrayList<Integer> lo2 = null;
			ArrayList<Integer> lo3 = null;
			ArrayList<Integer> lo4 = null;
			if (i < layout.possibleLayouts.size()) {
				lo2 = layout.possibleLayouts.get(i++);
			}
			if (i < layout.possibleLayouts.size()) {
				lo3 = layout.possibleLayouts.get(i++);
			}
			if (i < layout.possibleLayouts.size()) {
				lo4 = layout.possibleLayouts.get(i);
			}

			StringBuffer buf = new StringBuffer();
			printFirstLine(layout.gameSize, lo1, buf);
			printFirstLine(layout.gameSize, lo2, buf);
			printFirstLine(layout.gameSize, lo3, buf);
			printFirstLine(layout.gameSize, lo4, buf);
			buf.append("\n");
			
			for (int j = 0; j < layout.gameSize - 1; j++) {
				printMidLines(layout.gameSize, lo1, buf, j);
				printMidLines(layout.gameSize, lo2, buf, j);
				printMidLines(layout.gameSize, lo3, buf, j);
				printMidLines(layout.gameSize, lo4, buf, j);				
				buf.append("\n");
			}
			
			printLastLine(layout.gameSize, lo1, buf);
			printLastLine(layout.gameSize, lo2, buf);
			printLastLine(layout.gameSize, lo3, buf);
			printLastLine(layout.gameSize, lo4, buf);
			
			//buf.append("\n");
			logger.output(buf.toString());
		}
		logger.output(" ");
	}
}
